package designpattern;

/**
 * 工厂模式实现
 * 1. 简介
 * 提供了一种创建对象的最佳方式,在工厂模式中创建对象时不会暴露床架逻辑，
 * 并且是通过使用一个共用的接口来指向新的创建的对象
 * 主要解决：主要解决接口选择的问题。
 * 何时使用：我们明确地计划不同条件下创建不同实例时。
 * 2. 优点
 * (1) 拓展性高
 * (2) 屏蔽了产品的具体实现
 * 3. 缺点
 * 新增一个产品时需要添加一个具体的类和实现工厂
 * 4. 注意
 * 作为创建模式，在任何需要创建复杂对象的地方都可以使用工厂模式，但是对于简单对象特别时只需要new就库完成创建的对象，
 * 无需使用工厂模式
 * 5. 实现步骤
 * //1. 创建一个接口Shape
 * //2. 创建Shape接口对应的实现类 
 * //3. 创建一个工厂
 * //4. 使用工厂创建对象
 */
public class FactoryTest {
    public static void main(String[] args) {
        //1. 创建一个接口Shape
        //2. 创建Shape接口对应的实现类
        //3. 创建一个工厂
        //4. 使用工厂创建对象
        ShapeFactory shapeFactory = new ShapeFactory();
        //调用 Circle 的 draw 方法
        Shape circle = shapeFactory.getShape("CIRCLE", 1);
        circle.draw("圆形");
        float area = circle.area();
        System.out.println(area);

        //获取 Square 的对象，并调用它的 draw 方法
        Shape square = shapeFactory.getShape("SQUARE", 1, 2);
        square.draw("椭圆形");
        System.out.println(square.area());
    }
}

/**
 * 1. 创建一个接口Shape
 */
interface Shape {
    void draw(String name);

    float area();
}


/**
 * 2. 创建Shape接口对应的实现类
 */
class Circle implements Shape {
    float r;

    public Circle(float r) {
        this.r = r;
    }

    @Override
    public void draw(String name) {
        System.out.println("Inside Circle::draw() method." + name);
    }

    @Override
    public float area() {
        return (float) (r * r * Math.PI);
    }
}

/**
 * 2. 创建Shape接口对应的实现类
 */
class Square implements Shape {
    private float len;
    private float wide;

    public Square(float len, float wide) {
        this.len = len;
        this.wide = wide;
    }

    @Override
    public void draw(String name) {
        System.out.println("Inside Square::draw() method." + name);
    }

    @Override
    public float area() {
        return len * wide;
    }

}

/**
 * 3. 创建一个工厂
 */
class ShapeFactory {

    public Shape getShape(String shapeType, int... args) {
        if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square(args[0], args[1]);
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle(args[0]);
        }
        return null;
    }
}
